# coding:utf-8
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.chrome.options import Options
from time import sleep
import urllib.request
import cv2
import numpy as np
import os
import logging


class WSing:
    def __init__(self):
        self.root_url = "http://5sing.kugou.com"
        self.url = self.redUrl()
        chrome_options = Options()
        # chrome_options.add_argument('--headless')
        self.driver = webdriver.Chrome(executable_path=os.getcwd() + "\drivers\chromedriver.exe",options=chrome_options)
        logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                            level=logging.DEBUG)

    # 随机回复
    def randomReply(self):
        f = open("reply.txt", 'r', encoding='UTF-8')
        reply = f.readlines()
        import random
        num = random.randint(0, len(reply) - 1)
        return reply[num]

    # 读取Url
    def redUrl(self):
        f = open("url.txt", 'r', encoding='UTF-8')
        url = f.readlines()
        return url[0].strip("\n")

    def isElementExist(self,by, value):
        try:
            self.driver.find_element(by=by, value=value)
            return True
        except:
            return False

    # 登录网站
    def get_login(self, user, password):
        self.driver.get(self.root_url)
        self.driver.switch_to.default_content()
        self.driver.find_element_by_xpath("/html/body/div[1]/div/div/div[2]/ul[1]/li[1]/a").click()
        self.driver.find_element_by_css_selector("[class='btn user-sign-btn']").click()
        self.driver.find_element_by_class_name("user-input").clear()
        self.driver.find_element_by_class_name("user-input").send_keys(user)
        self.driver.find_element_by_class_name("pwd-input").clear()
        self.driver.find_element_by_class_name("pwd-input").send_keys(password)
        self.driver.find_element_by_css_selector("[class='login-btn active']").click()
        sleep(2)
        if self.isElementExist("id","tcaptcha_popup") == False: # 判断是否出现验证码
            self.get_login(user,password)
        return True

    # 获取验证码中的图片
    def get_image(self):
        iframe = self.driver.find_element_by_xpath('//*[@id="tcaptcha_popup"]')  # 找到“嵌套”的iframe
        self.driver.switch_to.frame(iframe)  # 切换到iframe
        image1 = self.driver.find_element_by_xpath('//*[@id="slideBkg"]').get_attribute('src') # 底部图片
        image2 = self.driver.find_element_by_xpath('//*[@id="slideBlock"]').get_attribute('src') # 滑块图片
        req = urllib.request.Request(image1)
        bkg = open('.\\img\\slide_bkg.png', 'wb+')
        bkg.write(urllib.request.urlopen(req).read())
        bkg.close()
        req = urllib.request.Request(image2)
        blk = open('.\\img\\slide_block.png', 'wb+')
        blk.write(urllib.request.urlopen(req).read())
        blk.close()
        return '.\\img\\slide_bkg.png', '.\\img\\slide_block.png'

    #计算缺口的位置，由于缺口位置查找偶尔会出现找不准的现象，这里进行判断，如果查找的缺口位置x坐标小于450，我们进行刷新验证码操作，重新计算缺口位置，知道满足条件位置。（设置为450的原因是因为缺口出现位置的x坐标都大于450）
    def get_distance(self,bkg,blk):
        block = cv2.imread(blk, 0)
        template = cv2.imread(bkg, 0)
        cv2.imwrite('.\\img\\template.jpg', template)
        cv2.imwrite('.\\img\\block.jpg', block)
        block = cv2.imread('.\\img\\block.jpg')
        block = cv2.cvtColor(block, cv2.COLOR_BGR2GRAY)
        block = abs(255 - block)
        cv2.imwrite('.\\img\\block.jpg', block)
        block = cv2.imread('.\\img\\block.jpg')
        template = cv2.imread('.\\img\\template.jpg')
        result = cv2.matchTemplate(block,template,cv2.TM_CCOEFF_NORMED)
        x, y = np.unravel_index(result.argmax(),result.shape)
        #这里就是下图中的绿色框框
        cv2.rectangle(template, (y+20, x+20), (y + 136-25, x + 136-25), (7, 249, 151), 2)
        #之所以加20的原因是滑块的四周存在白色填充
        # print('x坐标为：%d'%(y+20))
        if y+20<450: # 判断验证码识别是否正确
            # elem=driver.find_element_by_xpath('//*[@id="reload"]/div')
            self.driver.find_element_by_id("reload").click()
            self.driver.switch_to.default_content()
            bkg,blk=self.get_image()
            y,template=self.get_distance(bkg,blk)
            # print( bkg,blk)
        return y,template

    #这个是用来模拟人为拖动滑块行为，快到缺口位置时，减缓拖动的速度，服务器就是根据这个来判断是否是人为登录的。
    def get_tracks(self,distance,dis):
        v = 0
        t = 1
        #保存1内的位移
        tracks=[]
        current=0
        mid=distance*4/5
        while current<=dis:
            if current<mid:
                a = 2
            else:
                a = -3
            v0=v
            s=v0*t+0.5*a*(t**2)
            current+=s
            tracks.append(round(s))
            v=v0+a*t
        return tracks

    def Slide(self):
        bkg, blk = self.get_image()
        distance, template = self.get_distance(bkg, blk)
        double_distance = int((distance - 70 + 40) / 2)
        tracks = self.get_tracks(distance, double_distance)
        tracks.append(-(sum(tracks) - double_distance))
        element = self.driver.find_element_by_id('tcaptcha_drag_thumb')
        ActionChains(self.driver).click_and_hold(on_element=element).perform()
        for track in tracks:
            ActionChains(self.driver).move_by_offset(xoffset=track, yoffset=0).perform()
        sleep(0.5)
        ActionChains(self.driver).release(on_element=element).perform()
        sleep(1.5)
        if self.isElementExist("id","slideBlock")==True: #判断是否验证成功
            logging.warning('验证失败，请求重试。')
            self.driver.find_element_by_id("reload").click()
            self.driver.switch_to.default_content()
            sleep(1.5)
            self.Slide()
        logging.info('登入成功 !!!')

    def Reply(self,User):
        js = 'window.open("{}");'.format(self.url)
        self.driver.execute_script(js)

        n = self.driver.window_handles  # 获取当前页句柄
        self.driver.switch_to.window(n[1])  # 切换到新的网页窗口
        sleep(1.5)
        self.driver.refresh()
        sleep(1.5)

        self.driver.find_element_by_xpath('//*[@id="comments_container_anchor"]/div[2]/div[4]/textarea[2]').clear()
        message = self.randomReply()
        self.driver.find_element_by_xpath('//*[@id="comments_container_anchor"]/div[2]/div[4]/textarea[2]').send_keys(
            message)
        try:
            self.driver.find_element_by_xpath('//*[@id="comments_container_anchor"]/div[2]/div[5]/span[2]/input').click()
        except Exception:
            logging.error( User + "   需邮箱/手机验证后才能发言，验证邮箱 | 手机 !!! ")
            # print(str(datetime.datetime.now()) + "----" + User + "----需邮箱/手机验证后才能发言，验证邮箱 | 手机 !!! ")
        self.driver.delete_all_cookies()
        try:
            os.remove(".\\img\\block.jpg")
            os.remove(".\\img\\slide_bkg.png")
            os.remove(".\\img\\slide_block.png")
            os.remove(".\\img\\template.jpg")
        except Exception:
            logging.warning('没有需要删除的文件！！！')
        sleep(1.5)
        self.driver.delete_all_cookies()
        self.driver.close()
        self.driver.switch_to.window(n[0])
        self.driver.refresh()

    def run(self):
        f = open("user.txt", "r", encoding="utf-8")
        for UPStr in f.readlines():
            User, Pass = UPStr.split("----")
            self.get_login(User, Pass)
            self.Slide()
            self.Reply(User)
        self.driver.quit()

if __name__ == '__main__':
    W = WSing()
    W.run()
